{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def gradient(fun, x, delta=1e-4):\n",
    "    x = np.asfarray(x)\n",
    "    grad = np.zeros(x.shape, dtype=x.dtype)\n",
    "\n",
    "    for i, t in np.ndenumerate(x):\n",
    "        x[i] = t + delta\n",
    "        grad[i] = fun(x)\n",
    "        x[i] = t - delta\n",
    "        grad[i] -= fun(x)\n",
    "        x[i] = t\n",
    "\n",
    "    return grad / (2 * delta)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## quadratic form"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x= -1 grad= [-4.]\n",
      "x= 0 grad= [ 2.]\n",
      "x= 1 grad= [ 8.]\n"
     ]
    }
   ],
   "source": [
    "def function(x):\n",
    "    return 3 * x**2 + 2 * x + 1\n",
    "\n",
    "for x in [-1, 0, 1]:\n",
    "    print('x=', x, 'grad=', gradient(function, [x]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## transcendental function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x= [0, 0, 0] grad= [ 0.  1.  1.]\n",
      "x= [0, 0, 1] grad= [ 1.84147099  1.54030231  1.        ]\n",
      "x= [0, 1, 1] grad= [ 3.55975282  3.25858414  1.87681085]\n",
      "x= [1, 1, 1] grad= [ 8.2305271   7.92935842  7.08788742]\n"
     ]
    }
   ],
   "source": [
    "def function(X):\n",
    "    x, y, z = X\n",
    "    return x * np.sin(z) + y * np.cos(z) + z * np.exp(x + y)\n",
    "\n",
    "for x in [[0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 1, 1]]:\n",
    "    print('x=', x, 'grad=', gradient(function, x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## determinant"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x=\n",
      "[[1, 2, 3], [2, 3, 1], [3, 1, 2]]\n",
      "grad=\n",
      "[[ 5. -1. -7.]\n",
      " [-1. -7.  5.]\n",
      " [-7.  5. -1.]]\n",
      "x=\n",
      "[[1, 1, 1], [1, 1, 1], [1, 1, 1]]\n",
      "grad=\n",
      "[[ 0.  0.  0.]\n",
      " [ 0.  0.  0.]\n",
      " [ 0.  0.  0.]]\n",
      "x=\n",
      "[[1, 1], [1, 1]]\n",
      "grad=\n",
      "[[ 1. -1.]\n",
      " [-1.  1.]]\n"
     ]
    }
   ],
   "source": [
    "function = np.linalg.det\n",
    "\n",
    "for x in [\n",
    "    [[1, 2, 3], [2, 3, 1], [3, 1, 2]],\n",
    "    [[1, 1, 1], [1, 1, 1], [1, 1, 1]],\n",
    "    [[1, 1], [1, 1]],\n",
    "]:\n",
    "    print('x=')\n",
    "    print(x)\n",
    "    print('grad=')\n",
    "    print(gradient(function, x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
